#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <sys/time.h>

#include "data_type.h"
#include "beidou_service.h"

#include "comm.h"

#include <libubus.h>
#include <libubox/blobmsg.h>
#include <libubox/uloop.h>

NMEA_Data BD_Location;
NMEA_Data BD_Date;

static int fd;
extern char *bd_dev;
extern int bd_speed;
struct blob_buf time_buf;
typedef struct energy_info{
    uint16_t    addr;
    uint8_t     date[25];
    uint8_t     sleepTime[9];
    uint8_t     workTime[9];
    uint8_t     runTime[25];
}tEnergyInfo;
/**
 * 字符串时间转时间戳
 */
int standard_to_stamp(char *str_time, int zone){
    struct tm stm;
    int iY,iM,iD,iH,iMin,iS;
    memset(&stm,0,sizeof(stm));
    iY = atoi(str_time);
    iM = atoi(str_time+5);
    iD = atoi(str_time+8);
    iH = atoi(str_time+11);
    iMin = atoi(str_time+14);
    iS = atoi(str_time+17);

    stm.tm_year = iY - 1900;
    stm.tm_mon = iM - 1;
    stm.tm_mday = iD;
    stm.tm_hour = iH;
    stm.tm_min = iMin;
    stm.tm_sec = iS;

    return (int) mktime(&stm) + zone * 60 * 60;
}
// 将给定的年、月、日、时、分、秒转换为time_t
time_t make_time(int year, int month, int day, int hour, int minute, int second) {
    struct tm given_tm = {0};
    
    given_tm.tm_year = year - 1900;  // 年份从1900开始计算
    given_tm.tm_mon = month - 1;     // 月份从0开始（0=1月）
    given_tm.tm_mday = day;
    given_tm.tm_hour = hour;
    given_tm.tm_min = minute;
    given_tm.tm_sec = second;
    given_tm.tm_isdst = -1;          // 自动判断夏令时
    
    return mktime(&given_tm);
}

// 比较两个时间差
int is_time_diff_greater(time_t time1, time_t time2) {
    double diff = difftime(time1, time2);
    if (diff < 0) {
        diff = -diff; // 取绝对值
    }
    return diff;
}
// 将时间转换为可读格式
void print_time(const char* label, time_t t) {
    struct tm* timeinfo = localtime(&t);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo);
    printf("%s: %s\n", label, buffer);
}
void beidou_printf(const char *format, ...)
{
    char buffer[256]={'\0'};
    va_list args;
    va_start(args, format);
    int len = vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);
    printf("beidou_printf:%s, len: %d\n", buffer, len);
    lx_serial_write(fd, buffer, len);
}

static const struct blobmsg_policy energy_info_policy[] = {
    [0] = { .name = "date",         .type = BLOBMSG_TYPE_STRING },
};
/**
 * 获取端口状态数据
 */
static void energy_info_callback(struct ubus_request *req, int type, struct blob_attr *msg) {

    if (!msg) {
        return;
    }
    // 解析内存数据
    struct blob_attr *tb[1];
    blobmsg_parse(energy_info_policy, ARRAY_SIZE(energy_info_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));

    if(tb[0]) {
        uint8_t *dateTime = blobmsg_get_string(tb[0]);
        if(dateTime != NULL){
            struct tm tm = {0};
            time_t timestamp;
            // 使用 strptime 解析时间字符串
            char *result = strptime(dateTime, "%Y-%m-%d %H:%M:%S", &tm);
            
            if (result == NULL) {
                printf("时间字符串解析失败\n");
                return -1;
            }
            
            // 设置时区标志（-1 表示自动检测夏令时）
            tm.tm_isdst = -1;
            
            // 将 tm 结构转换为时间戳
            timestamp = mktime(&tm);
            if (timestamp == -1) {
                printf("时间转换失败\n");
                return -1;
            }
            time_t system_time = time(NULL);
            if(is_time_diff_greater(timestamp, system_time) > 5){
                char date_str[35]={0};
                sprintf(date_str, "date -s '%04d-%02d-%02d %02d:%02d:%02d'", \
                    BD_Date.datetime.year, BD_Date.datetime.month, BD_Date.datetime.day,\
                    (BD_Date.datetime.hour+8), BD_Date.datetime.min, BD_Date.datetime.sec);
                
                int status = system(date_str);
                
                if (status == -1) {
                    perror("system()执行失败");
                } else if (WIFEXITED(status)) {
                    printf("系统时间命令退出状态: %d\n", WEXITSTATUS(status));
                }
                sleep(1);
                status = system("ubus call sihan.energy sync_timer");
                
                if(status == 0){
                    printf("校时成功......\n");
                } else {
                    printf("校时失败......\n");
                }
            }
        }
        
    }
}
int read_energy_status_data() {
    // 连接 ubus
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "Failed to connect to ubus\n");
        return -1;
    }
    // 查找 network.device 的 ID
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "sihan.energy", &obj_id) != 0) {
        fprintf(stderr, "Failed to lookup sihan.bridge\n");
        ubus_free(ctx);
        return -1;
    }

    blob_buf_init(&time_buf, 0);
    // 发起异步调用
    int ret = ubus_invoke(ctx, obj_id, "query_timeinfo", time_buf.head, energy_info_callback, NULL, 3000);
    if (ret == 0) {
        
    }
    
    // 清理资源
    blob_buf_free(&time_buf);
    ubus_free(ctx);
    return 0;
}

void beidou_timing(){
    if (BD_Date.status == 0 && BD_Date.type == NMEA_TYPE_GNZDA)
    {
        time_t beidou_time = make_time(BD_Date.datetime.year, BD_Date.datetime.month, BD_Date.datetime.day, \
                BD_Date.datetime.hour+8, BD_Date.datetime.min, BD_Date.datetime.sec);
        time_t system_time = time(NULL);
        

        read_energy_status_data();  //校时电源模块

        if(is_time_diff_greater(beidou_time, system_time) > 5) {    //校时核心板
            print_time("北斗时间：", beidou_time);
            print_time("系统时间：", system_time);
            char date[35]={0};
            sprintf(date, "date -s '%04d-%02d-%02d %02d:%02d:%02d'", \
                BD_Date.datetime.year, BD_Date.datetime.month, BD_Date.datetime.day,\
                (BD_Date.datetime.hour+8), BD_Date.datetime.min, BD_Date.datetime.sec);
            #if 1
            int status = system(date);
            
            if (status == -1) {
                perror("system()执行失败");
            } else if (WIFEXITED(status)) {
                printf("系统时间命令退出状态: %d\n", WEXITSTATUS(status));
            }
            
            sleep(1);

            status = system("hwclock -w");
            
            if (status == -1) {
                perror("system()执行失败");
            } else if (WIFEXITED(status)) {
                printf("硬件时钟命令退出状态: %d\n", WEXITSTATUS(status));
            }
            #endif
        }
        
    }
}
/**
 * 北斗数据接收线程
 */
int gather_worker() {
    if (bd_dev == NULL)
    {
        /* code */
        printf("设备无效\n");
        return -1;
    }
    
    fd = lx_serial_open(bd_dev, bd_speed);
    CHECK_FAILED(fd, 0);
    unsigned int dataIdx = 0;
    char data[1024]={0};

    #define BUFFER_SIZE 256
    char buffer[BUFFER_SIZE];
    char nmea_buffer[1024] = {0};
    int total_bytes = 0;

    while(true) {
        int bytes_read = read(fd, buffer, BUFFER_SIZE - 1);
        if (bytes_read > 0) {
            buffer[bytes_read] = '\0';
            strncat(nmea_buffer, buffer, bytes_read);
            total_bytes += bytes_read;

            // 检测帧尾
            char *frame_end = strstr(nmea_buffer, "\r\n");
            if (frame_end != NULL) {
                *frame_end = '\0'; // 截断完整帧
                // 处理数据（例如解析GGA、RMC语句）
                if(strncmp(nmea_buffer, "$GNGGA", 6) == 0){
                    BD_Location = parse_nmea(nmea_buffer);
                    if(BD_Location.status == 0){
                        BD_Location.datetime.hour += 8;
                    }
                    //print_data(&BD_Location);
                }
                if(strncmp(nmea_buffer, "$GNZDA", 6) == 0){
                    BD_Date = parse_nmea(nmea_buffer);
                    beidou_timing();
                    //print_data(&BD_Date);
                }
                // 清空缓冲区剩余数据
                memmove(nmea_buffer, frame_end + 2, total_bytes - (frame_end - nmea_buffer));
                total_bytes -= (frame_end - nmea_buffer) + 2;
            }
        }

    }
    lx_serial_close(fd);
    return 0;
    failed_0:
    return -1;
}
/**北斗数据获取线程 */
int ep_gather_start(void)
{
    pthread_t pid1;
    pthread_create(&pid1, NULL, gather_worker, NULL);
    return 0;
}
